home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 3
/
csmp-digest-v3-116
< prev
next >
Wrap
Text File
|
1995-12-31
|
79KB
|
2,159 lines
C.S.M.P. Digest Fri, 13 Oct 95 Volume 3 : Issue 116
Today's Topics:
ANSI C++, exceptions, globals, etc, in shared libs?!?
Creating an Alias
DNR lib and MacTCP.h
Getting Volume Icon?
How do I tell if Time Manager task install was successful?
How to unlock a volume?
MakeDataExecutable()?
Q: Open-Close PPP from Code?
QuickTime JPEG help
Storing data in text portion of an application
Why doesn't the Dialog Manager recognize I moved some controls?
[Q] Changing Pixmap resolution???
[Q] Traps not callable from interrupt, why?
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroups
comp.sys.mac.programmer.help, csmp.tools and csmp.misc. It is designed for
people who read news semi-regularly and want an archive of the discussions.
If you don't know what a newsgroup is, you probably don't have access to
it. Ask your systems administrator(s) for details. If you don't have access
to news, you may still be able to post messages to the group by using a
mail server like anon.penet.fi (mail help@anon.penet.fi for more
information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu.
-------------------------------------------------------
>From jessholl@netcom.com (Jess Holle)
Subject: ANSI C++, exceptions, globals, etc, in shared libs?!?
Date: Sun, 8 Oct 1995 03:48:13 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
I have several applications which use one common class framework. In CW 6
I made another version of the C runtime library which seemed to work fine
from shared libraries and support the use of the ANSI C library from both
the shared library and my applications.
In CW 7, I made another version of the C runtime library in _exactly_ the
same way, rebuilt all precompiled headers and projects, and then got
_lots_ of link errors. This was not too much of a surprise since I made
one crucial change: I turned direct destruction off and turned C++
exceptions on. I did this because the release notes state that this is
necessary if you use C++ iostreams. Also, I wish to use exceptions in the
not too distant future and wanted to make sure that I could when I wanted
to.
I have seen lengthy posts from John McEnernery and other Metrowerks people
on how to modify the standard library projects to allow them to work in a
shared library environment. I thank them for their efforts. There are
two problems with this, however:
1) I have not seen a post yet which gives step by step instructions to
create a single "standard" project or set of projects which allows ANSI
C and C++ libraries to be used from any PowerPC shared library or
application, handling exceptions, exit(), abort(), setjmp(), longjmp(),
Quickdraw globals, SIOUX, etc. Basically I want to know that all these
issues are handled so I can have _some_ faith in the runtime mechanisms
while using shared libraries.
2) As illustrated by my problems when moving from CW6 to CW7, shared
library support is somewhat shaky unless shared-library "ready" versions
of the ANSI and runtime libraries are provided either in the release or
on the web site. Let me explain. Assume that I make all the changes
necessary to the ANSI and runtime libraries in order to achieve the
perfect shared-library ready support libraries. Next CW8 comes out and
I have to revamp these support libraries, as does everyone else who has
done such tinkering. Same goes for CW version N. This would also seem
to create a technical support nightmare (or is no one using shared
libraries all that much?)
Don't get me wrong. Metrowerks is doing a fantastic job. Code Warrior is
a joy to use overall. It seems, however, that using the ANSI and runtime
support libraries with shared libraries has been unnecessarily left as a
black art.
If anyone has successfully created versions of the runtime library that
allow the use of:
- Quickdraw globals,
- exceptions,
- abort(), exit(), setjmp(), etc,
- ANSI C and C++ libraries, and
- SIOUX
from within shared libraries with no strange restrictions, I would love to
hear from them.
It would be ideal if several wise people could whip together the projects
necessary and get them placed on Metrowerks web site and/or release CDs.
It would even better if this was done by Metrowerks so these projects had
full technical support, bug fixing, and maintenance from release to
release.
I'm sorry to have run on so long. It just seems that shared libraries are
becoming an important part of the Mac runtime environment, especially when
using one or more common frameworks. It therefore seems that solid,
standard runtime support for this environment should be part of the
development package, not something that must be hacked out with each
release of the runtime libraries.
Sincerely,
Jess Holle
- -------------------------------------------------------------------
Jess Holle / jessholl@netcom.com
Norwood, MA / ftp://ftp.netcom.com/pub/je/jessholl/j_and_w_www.html
+++++++++++++++++++++++++++
>From ari@shore.net (Ari Halberstadt)
Date: Wed, 11 Oct 1995 16:19:10 -0400
Organization: North Shore Access/Eco Software, Inc; (info@shore.net)
In article <jessholl-0710952350220001@10.0.2.15>, jessholl@netcom.com
(Jess Holle) wrote:
>...
> 1) I have not seen a post yet which gives step by step instructions to
> create a single "standard" project or set of projects which allows ANSI
> C and C++ libraries to be used from any PowerPC shared library or
> application, handling exceptions, exit(), abort(), setjmp(), longjmp(),
> Quickdraw globals, SIOUX, etc. Basically I want to know that all these
> issues are handled so I can have _some_ faith in the runtime mechanisms
> while using shared libraries.
>...
>If anyone has successfully created versions of the runtime library that
>allow the use of:
> - Quickdraw globals,
> - exceptions,
> - abort(), exit(), setjmp(), etc,
> - ANSI C and C++ libraries, and
> - SIOUX
>from within shared libraries with no strange restrictions, I would love to
>hear from them.
>...
I do not have a complete solution to your request. However, I can help you
with supporting setjmp, longjmp, and QuickDraw global variables in plain
ANSI C code (I have not done this with C++ code). My shared library does
not use the full ANSI library. To use setjmp and longjmp, add the files
setjmp.o and runtime.o from the runtime folder to your library's project.
Use a .exp file to specify the symbols to export. Make sure you do not
export longjmp from your library. You will also need to declare a dummy
destructor chain:
void *__local_destructor_chain;
When you call setjmp, make sure that it is called directly in the code
fragment to which you want the call to apply. This ensures that the
correct TOC register is saved. Similarly, when you call longjmp, you must
ensure that the longjmp corresponding to the setjmp you had called is
used. For instance, if you call setjmp from fragment a, then you must also
call the longjmp compiled with fragment a, even if you call the longjmp
while executing code in fragment b. The solution I found was to store a
pointer to the longjmp function at the time setjmp is called. Something
like the following,
struct JumpEnvironment {
jmp_buf jmpbuf;
LongjmpPtr jump;
};
JumpEnvironment env;
env->jump = longjmp;
if (setjmp(env->jmpbuf) == 0) ...
...
env->jump(env->jmpbuf, 1);
...
This precaution guards against the possibility that the jump buffer's
format could be different in the two shared libraries. This actually
happened to me when I used setjmp.o in one library but used a different
setjmp in a second library (via the ANSI library).
Last week I posted one method of accessing QuickDraw global variables from
a shared library. Here is the post again (including a few slight errors).
Also enclosed is a reply describing an alternative method.
Path: shore!slip-5-3.shore.net!user
From: ari@shore.net (Ari Halberstadt)
Newsgroups: comp.sys.mac.programmer.codewarrior,alt.sources.mac
Subject: My recipe for QD globals in shared lib (was Re: shared libraries
and quickdraw globals)
Date: Mon, 25 Sep 1995 01:10:41 -0400
Organization: North Shore Access/Eco Software, Inc; (info@shore.net)
Lines: 245
Message-ID: <ari-2509950110410001@slip-5-3.shore.net>
References: <4357i3$ags@colossus.holonet.net> <coopmanDF9zB6.Jo5@netcom.com>
Reply-To: comp.sys.mac.programmer.codewarrior
NNTP-Posting-Host: slip-5-3.shore.net
Xref: shore comp.sys.mac.programmer.codewarrior:25526 alt.sources.mac:2507
Accessing the QuickDraw global variables from a fragment is not as simple as
"Inside Macintosh:PowerPC System Software" [IM:PPCSS] might lead you to believe.
IM:PPCSS, p1-57 to 1-63 says that a limited A5 world is created for
applications.
This limited A5 world supposedly provides access to the QuickDraw global
variables using the technique documented in "Inside Macintosh: Memory", p4-18 to
p4-19. It turns out, however, that Metrowerks CodeWarior v6 does not
configure the A5 world in a manner allowing this technique to work*. For
PPC-native code, you need to use the Code Fragment Manager to locate the
QuickDraw
global variables. This document provides a recipe, of sorts, for doing this.
Disclaimer: The code and steps provided in this document are based on my own
code. However, these specific code examples have not been tested. Use at
your own
risk.
* I may just be confused in my reading of IM:PPCSS or my analysis of the
A5 world
generated by Codewarrior. At any rate, I could not get the technique
described in
IM:Memory to work in a native PowerPC application, but I could get it to work in
an emulated 68K application.
Modifications to your shared library
====================================
The following modifications allow your shared library to resolve, at
runtime, the
address of the QuickDraw global variables.
- Define a couple of functions to locate a symbol.
/* CurrentProcessConnectionID returns the connection ID for the fragment located
in the current process's application file. This is based on "InitResource.c",
by Mark Anderson of Metrowerks. */
OSErr CurrentProcessConnectionID(CFragConnectionID *connectionID)
{
Ptr mainAddress;
Str255 errorMessage;
Str255 processName;
FSSpec processSpec;
ProcessSerialNumber psn;
ProcessInfoRec processInfo;
OSErr err;
processInfo.processInfoLength = sizeof(ProcessInfoRec);
processInfo.processName = processName;
processInfo.processAppSpec = &processSpec;
psn.highLongOfPSN = 0;
psn.lowLongOfPSN = kCurrentProcess;
err = GetProcessInformation(&psn, &processInfo);
if (! err) {
err = GetDiskFragment(&processSpec, 0L, 0L, processName, kFindCFrag,
connectionID, &mainAddress, errorMessage);
}
return(err);
}
/* FindSymbolInSelfOrCaller searches for a symbol first in the
current fragment and then in the fragment for the current
process. */
OSErr FindSymbolInSelfOrCaller(ConstStr255Param symbolName,
Ptr *symbolAddress,
SymClass *symbolClass)
{
CFragConnectionID currentID;
OSErr err;
err = FindSymbol(gInitBlock.connectionID, symbolName, symbolAddress,
symbolClass);
if (err == fragSymbolNotFound) {
err = CurrentProcessConnectionID(¤tID);
if (! err)
err = FindSymbol(currentID, symbolName, symbolAddress, symbolClass);
}
return(err);
}
- Define a start symbol for your code fragment. Something like:
/* Copy of initialization block passed to wsCFInitialize. */
CFragInitBlock gInitBlock;
/* The fragment's initialization function. */
OSErr Initialize(CFragInitBlockPtr initBlock)
{
gInitBlock = *initBlock;
return(noErr);
}
This just saves a copy of the initialization block passed to the fragment. We
make a copy of the initialization block because "Inside Macintosh: PowerPC
System
Software" does not indicate the scope of the pointer to the initialization
block.
It appears that the initialization block remains valid as long as the fragment
remains loaded, but this little fact is not documented. This means, for
instance,
that we cannot really be certain that the fields of the CFragHFSLocator
are valid
after the initialization function returns. We are only interested, however, in
the connection and context IDs, which are just long integers, so a copy of the
initialization block will work ok.
Note: instead of using the Process Manager to locate the file containing
the fragment, we could use the fragLocator field of the CFragInitBlock
record.
- Set the initialization function of your fragment. If you're using Metrowerks
CodeWarrior, then enter the initialization function's name in the
"Initialization" entry point field in the "Linker" pane of the preferences
dialog
for your fragment's project file.
- Add the following declaration in some common header file:
extern QDGlobals *gQDGlobals;
Also, add the following definition in some source file:
QDGlobals *gQDGlobals;
- Do a global search and replace and change all references to "qd." to
"gQDGlobals->", and then change all references to "qd" (without the member
access operator) to "gQDGlobals".
- Add the following lines before you first use the QuickDraw global variables:
#if GENERATINGCFM
CFragSymbolClass symbolClass;
OSErr err;
err = FindSymbolInSelfOrCaller((StringPtr) "\pqd", (Ptr *)
&gQDGlobals, &symbolClass);
if (err != noErr)
/* handle the error, probably just ExitToShell */;
#else
gQDGlobals = (QDGlobals *) ((*(long *) SetCurrentA5()) -
sizeof(QDGlobals) + sizeof(GrafPtr));
#endif
- Rebuild your fragment.
Modifications to your application
=================================
The following modifications export the QuickDraw global variables from your
application, so that your shared library can access them.
- Generate a ".exp" file for the calling application. If you're using Metrowerks
CodeWarrior, then turn on "use “.exp” file" from the "Export Symbols" popup menu
in the "PEF" panel of the preferences dialog for your application's project and
remake the project. You may get a bunch of errors about undefined symbols, e.g.,
SIOUX and CodeWarrior runtime stuff; you can ignore these errors.
- Open the ".exp" file. The ".exp" file will initially contain all the global
symbols in your application. Remove everything but the symbols you want to
export, i.e., "qd". Remake the project again.
- Run. Hopefully, everything will work.
Accessing Functions
===================
This is an example of how you might use the above technique to locate functions.
I use code similar to the following examples to avoid having to include the ANSI
library in my shared library yet still be able to allocate memory (you could use
any application-defined memory allocation routines by changing the names of the
functions). Remember to add the names of any symbols you want to access in your
shared library to your application's ".exp" file.
#if GENERATINGCFM
#define FindSymbolNative(addr, name)
FindSymbolAddressInSelfOrCaller((StringPtr) name)
#else
#define FindSymbolNative(addr, name) (addr)
#endif
typedef void *(*MallocProcPtr)(size_t n);
typedef void (*FreeProcPtr)(void *p);
/* Returns the address of the malloc function. */
static MallocProcPtr FindMalloc(void)
{
static MallocProcPtr mallocProc;
if (! mallocProc)
mallocProc = FindSymbolNative(malloc, "\pmalloc");
return(mallocProc);
}
/* Returns the address of the free function. */
static FreeProcPtr FindFree(void)
{
static FreeProcPtr freeProc;
if (! freeProc)
freeProc = FindSymbolNative(free, "\pfree");
return(freeProc);
}
Notice that I use exceptions for error handling, so
FindSymbolAddressInSelfOrCaller
looks more like
void *FindSymbolAddressInSelfOrCaller(Str255 symbolName)
{
Ptr symbolAddress;
CFragSymbolClass symbolClass;
OSErr err;
err = FindSymbol(gInitBlock.connectionID, symbolName, &symbolAddress,
&symbolClass);
if (err == fragSymbolNotFound)
err = FindSymbol(CurrentProcessConnectionID(), symbolName,
&symbolAddress, &symbolClass);
ThrowIfOSErr(err);
assert(symbolAddress != NULL);
return(symbolAddress);
}
Unanswered Questions
====================
1. What are the contextID and closure ID fields in the CFragInitBlock
record? Could
these fields be used rather than locating the current process' file?
2. Is the pointer (and all fields) of the CFragInitBlock passed to the
initialization
routine guaranteed to remain valid for the duration of the connection to the
initialized fragment?
CodeWarrior 7 Bonuses
=====================
Debugging PPC shared libraries WORKS! Yippy! And the MetroNub doohicky
makes setting
conditional breakpoints feasible. I still get the stupid -108 error from
the Scrap
Manager, though. Also, I haven't quite gotten my 68K shared library to link.
-- Ari Halberstadt (ari@shore.net, ari@world.std.com)
For latest versions of some of my Macintosh software try
<ftp://ftp.shore.net/members/ari>.
Path:
shore!uunet!in2.uu.net!svc.portal.com!news1.best.com!shellx.best.com!ckt.vip.best.com!user
From: ckt@best.com (Chris Thomas)
Newsgroups: comp.sys.mac.programmer.codewarrior,alt.sources.mac
Subject: Re: My recipe for QD globals in shared lib (was Re: shared
libraries and quickdraw globals)
Date: Fri, 29 Sep 1995 01:40:19 -0800
Organization: Echo Software
Lines: 20
Message-ID: <ckt-2909950140190001@ckt.vip.best.com>
References: <4357i3$ags@colossus.holonet.net>
<coopmanDF9zB6.Jo5@netcom.com> <ari-2509950110410001@slip-5-3.shore.net>
NNTP-Posting-Host: ckt.vip.best.com
X-Newsreader: Yet Another NewsWatcher 2.0b30
Xref: shore comp.sys.mac.programmer.codewarrior:26014 alt.sources.mac:2537
If you control the application as well as the sharedlib, this
can be vastly simplified. Declare "QDGlobals qd" explicitly in
your app. Make sure the file with this declaration comes before
the MWCRuntime lib. Export "qd" using the .exp file. When you
link, you'll get a warning that the "qd" declaration in Startup.c
was ignored, which is what you want (alternately, you can comment
out the "QDGlobals qd" declaration in Startup.c and rebuild
MWCRuntime.)
In the sharedlib, either include the application as a shared
library or use a dummy shared library with the "qd" symbol
exported. Again, be sure this library is positioned before
MWCRuntime in the project file.
When the app connects to your code fragment, your app is still in
the loader's search path and connects qd up to the application's
qd automatically.
--
Chris Thomas, ckt@best.com
-- Ari Halberstadt (ari@shore.net, ari@world.std.com)
For latest versions of some of my Macintosh software try <ftp://ftp.shore.net/members/ari>.
---------------------------
>From strauss@ap.org (Fred Strauss)
Subject: Creating an Alias
Date: Wed, 27 Sep 1995 11:56:03 -0400
Organization: The Associated Press
Is there a way to create an alias of a file via Apple Events sent to the
Finder? What I'm trying to do from within an installer is create an alias
of an application in the startup items folder.
I see there is a script that came with System 7.5 called 'Add Alias to
Apple Menu' and I'm wondering if I could somehow call a modified version
of this script from my installer or mimic its functionality via apple
events to the finder?
Thanks,
Fred
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 29 Sep 1995 02:50:05 -0400
Organization: America Online, Inc. (1-800-827-6364)
Fred Strauss wrote:
>Is there a way to create an alias of a file via Apple Events
>sent to the Finder? What I'm trying to do from within an
>installer is create an alias of an application in the startup
>items folder.
Fred, you should start with the article "Scripting the Finder From Your
Application" by Greg Anderson in develop managzine, issue 20. You can find
that on Apple's Developer CD or on the web at:
http://www.info.apple.com/dev/develop/issue20/20anderson.html
The code for Greg's article is at:
ftp://ftp.info.apple.com/Apple.Support.Area/Developer_Services/Periodicals
/develop/develop20/develop_20_code/Scripting_the_Finder.sit.hqx
Hope that give you a good start.
- Jim Luther
---------------------------
>From Martin.Friedrich@arbi.informatik.uni-oldenburg.de (Martin Friedrich)
Subject: DNR lib and MacTCP.h
Date: Thu, 21 Sep 1995 09:58:02 GMT
Organization: University of Oldenburg, Germany
Hi, all!
I've noticed that the declaration of the DNR routines in MacTCP.h from the
Universal Headers don't match those in DNR.c. In MacTCP.h they're all
pascal OSErr, whereas in DNR.c they are OSErr declared. Is there a newer
(or say more uptodate) DNR-library I missed, or is this a bug in the
Universal Headers?
Thanks in advance,
Martin Friedrich
+++++++++++++++++++++++++++
>From scouten@uiuc.edu (Eric Scouten)
Date: Wed, 27 Sep 1995 10:21:04 -0500
Organization: Huh? What's that?
In article <1995Sep21.100351.13084@arbi.Informatik.Uni-Oldenburg.DE>,
Martin.Friedrich@arbi.informatik.uni-oldenburg.de (Martin Friedrich)
wrote:
> I've noticed that the declaration of the DNR routines in MacTCP.h from the
> Universal Headers don't match those in DNR.c. In MacTCP.h they're all
> pascal OSErr, whereas in DNR.c they are OSErr declared. Is there a newer
> (or say more uptodate) DNR-library I missed, or is this a bug in the
> Universal Headers?
The latest that I've seen has the declarations in <AddressXlation.h> and
the source in <dnr.c>. They are consistently declared as C functions (i.e.
no pascal keyword).
(This is the version shipping on CW/7 which is from Universal Headers 2.1b1.)
-es
__________________________________________________________________________
Eric Scouten Constructor Constructor
scouten@metrowerks.com Metrowerks, Inc.
If you still can't figure out how to get on the list, you're probably a
"Family Circus" fan anyway and not destined to mingle with the new ruling
class except maybe as domestic help.
-Scott Adams
---------------------------
>From rajadhyaksha.2@osu.edu (Ram Rajadhyaksha)
Subject: Getting Volume Icon?
Date: Sat, 23 Sep 1995 19:42:33 -0400
Organization: The Ohio State University
I want to do a cool volume selection dialog box with the icon of the
volume next to the pop-up menu. The question is, where the hell is the
icon data stored? I'm guessing that it's either an "Icon" file in the root
directory or something that is set on the driver level.
Any help is greatly appreciated...
-Ram
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 25 Sep 1995 02:52:01 -0400
Organization: America Online, Inc. (1-800-827-6364)
Ram Rajadhyaksha writes:
>I want to do a cool volume selection dialog box with the icon of
>the volume next to the pop-up menu. The question is, where the
>hell is the icon data stored? I'm guessing that it's either an
>"Icon" file in the root directory or something that is set on
>the driver level.
The standard icon for a drive can be obtained with PBControl and csCode
22. If you want the icon the Finder is showing, just ask the Finder for it
(assuming you're running the scriptable Finder). If you can't get it from
the Finder, then you'll need to check the root directory to see if it has
the hasCustomIcon Finder flag bit set and if so, read the ICON resource
out of the Icon(c/r) file in the root directory.
- Jim Luther
---------------------------
>From reed@medicine.wustl.edu (Thomas Reed)
Subject: How do I tell if Time Manager task install was successful?
Date: Wed, 27 Sep 1995 08:48:17 -0500
Organization: Washington University
One of my programs installs a Time Manager task that runs once every five
seconds. Unfortunately, my program does things sometimes that make me
think that the task wasn't successfully installed. Since InsXTime and
PrimeTime don't return any kind of error, I'm not sure how to verify
this. Anyone else know?
Thanks in advance!
-Thomas
=====================================================
Thomas Reed Washington University
reed@visar.wustl.edu Medical School
reed@medicine.wustl.edu Saint Louis, MO
http://medinfo.wustl.edu/~reed
- ---------------------------------------------------
Clothes make the man. Naked people have little or no
influence on society. -- Mark Twain
=====================================================
Opinions posted are not the opinions of Wash. U.
+++++++++++++++++++++++++++
>From ari@shore.net (Ari Halberstadt)
Date: Thu, 28 Sep 1995 01:21:43 -0400
Organization: North Shore Access/Eco Software, Inc; (info@shore.net)
In article <reed-2709950848170001@thomasmac.wustl.edu>,
reed@medicine.wustl.edu (Thomas Reed) wrote:
>One of my programs installs a Time Manager task that runs once every five
>seconds. Unfortunately, my program does things sometimes that make me
>think that the task wasn't successfully installed. Since InsXTime and
>PrimeTime don't return any kind of error, I'm not sure how to verify
>this. Anyone else know?
Try looking in the queue header (it's some low-mem global, I think), and
walk it in MacsBug till you hit your task. Or use a high-level debugger by
grabbing the address into a queue variable with the right structure so,
say, Metrowerks debugger can expand each next pointer. Give it a big time
value, so that it isn't removed and added while you're looking at the
queue, which, admittedly, is likely to change from moment to moment. Maybe
you can do a quick search of the queue with a loop, something like
for (task = GetFirstTask(); task != NULL && task != myTask; task =
GetNextTask(task))
;
if (task == NULL)
DebugStr("\p not there");
You could also change your task to increment a global variable. Set the
task to execute every second. Have some display routine (not called from
the task) print the variable (or look at it in the debugger). If it
doesn't increment every second, the task is hozed.
Also, remember to put in an ExitToShell patch to remove your task, this
killed almost 2 days of my time recently (1 day to figure out how stupid I
was to not remove the task, 1 day to figure out the patch). Here's my
patch:
/* Called on termination to do any final cleanup,
which, if it were not done, would cause a crash. */
static void CleanupFinal(void)
{
wsClockRemoveAll();
}
/* Patch for ExitToShell. This patch is used to remove things that must be
removed when the application terminates to prevent the system from
crashing. This patch is really just a precaution for situations where
wsAppExit does not get called. */
static UniversalProcPtr gExitToShell;
static pascal void PatchedExitToShell(void)
{
long oldA5;
oldA5 = SetCurrentA5();
SetToolTrapAddress(gExitToShell, _ExitToShell);
CleanupFinal();
(void) SetA5(oldA5);
ExitToShell();
}
static void PatchExitToShell(void)
{
if (wsMacVersion() < wskSystemVersion8) {
gExitToShell = GetToolTrapAddress(_ExitToShell);
SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) PatchedExitToShell,
kPascalStackBased, GetCurrentArchitecture()), _ExitToShell);
}
}
Copland is supposed to do the proper cleanup, so the patch isn't installed
under system 8.
-- Ari Halberstadt (ari@shore.net, ari@world.std.com)
For latest versions of some of my Macintosh software try <ftp://ftp.shore.net/members/ari>.
+++++++++++++++++++++++++++
>From scouten@uiuc.edu (Eric Scouten)
Date: Thu, 28 Sep 1995 13:24:49 -0500
Organization: Huh? What's that?
In article <reed-2709950848170001@thomasmac.wustl.edu>,
reed@medicine.wustl.edu (Thomas Reed) wrote:
> One of my programs installs a Time Manager task that runs once every five
> seconds. Unfortunately, my program does things sometimes that make me
> think that the task wasn't successfully installed. Since InsXTime and
> PrimeTime don't return any kind of error, I'm not sure how to verify
> this. Anyone else know?
InsXTime eventually calls Enqueue which doesn't fail unless you've managed
to form a bad queue -- in which case it fails so spectacularly that
there's really no question it failed. (Suffice it to say that return codes
would not be an issue.) If you can read 68K assembly, drop into MacsBug
and type "il Enqueue". You'll see what I mean.
Possible thoughts:
[1] You've passed a really wacked-out time interval to PrimeTime.
[2] You haven't restored your globals properly. On 68K (non-CFM), you need
to manually save and restore the A5 register.
If one of these doesn't explain it, perhaps you could post with more
details of what's (not?) happening. I'd also be willing to look at a short
snippet to see if there's anything obvious to me.
-es
__________________________________________________________________________
Eric Scouten Constructor Constructor
scouten@metrowerks.com Metrowerks, Inc.
This is the biggest thing since new coke.
- R. Schnieder (New York Times) trying out Windows 95
---------------------------
>From Rocco Moliterno <rocco@mbox.vol.it>
Subject: How to unlock a volume?
Date: 24 Sep 1995 14:50:32 GMT
Organization: Italia Online
The right way to lock/unlock a volume, by software flag, should be:
err = PBHGetVInfoSync(&pb);
pb.ioVAtrb |= 0x8000; //to lock
or
pb.ioVAtrb &=0x7FFF; //to unlock
err = PBSetVInfoSync(&pb);
No problems to lock, but is impracticable to unlock a volume (already
locked by software) because the volume IS LOCKED, as a result can't
write on it.
What is the TRUE right way?
Please, send answer (even) to : rocco@mbox.vol.it, because I can't read
this newsgroup even.
Thanks.
Rocco
Rocco Moliterno
rocco@mbox.vol.it
+++++++++++++++++++++++++++
>From chris-b@cs.auckland.ac.nz (chris-b)
Date: Wed, 27 Sep 1995 12:32:26 +1200
Organization: HyperMedia Unit, Comp Sci, Auckland University
In article <443r7o$9d5@mikasa.iol.it>, Rocco Moliterno <rocco@mbox.vol.it>
wrote:
>The right way to lock/unlock a volume, by software flag, should be:
>
> err = PBHGetVInfoSync(&pb);
> pb.ioVAtrb |= 0x8000; //to lock
> or
> pb.ioVAtrb &=0x7FFF; //to unlock
> err = PBSetVInfoSync(&pb);
>
>No problems to lock, but is impracticable to unlock a volume (already
>locked by software) because the volume IS LOCKED, as a result can't
>write on it.
I haven't tried it, but I think you'd have to walk the VCB queue and clear
(or is it set??) the bit(s) "manually".
Use the _GetVCBQHdr trap to get the head of the VCB queue.
ChrisB
- ---------------------------------------------------------------------
NewZealand:AucklandUniversity:ComputerScience:HyperMediaUnit:ChrisBurns
Internet: chris-b@cs.auckland.ac.nz
Phone: +64 9 373-7599 x6194
Fax: +64 9 373-7453 Async, therefore I am.
- ---------------------------------------------------------------------
---------------------------
>From Karl_A._Bunker@maceast.com (Karl A. Bunker)
Subject: MakeDataExecutable()?
Date: Fri, 22 Sep 95 11:13:49 EDT
Organization: MacEAST
In a discussion of self-modifying code, I've seen a reference to a toolbox
call "MakeDataExecutable". I can't find any documentation on this call in IM:
Memory, Think Ref., or in Apple's Headers. Anyone know where I can get some
info on it?
Karl Bunker
--
- ---------------------
via MacEAST, Boston
http://www.maceast.com/
+++++++++++++++++++++++++++
>From grobbins@znet.com (Grobbins)
Date: Mon, 25 Sep 1995 21:38:08 -0700
Organization: Skunkworks
In article <1465651.ensmtp@maceast.com>, Karl_A._Bunker@maceast.com (Karl
A. Bunker) wrote:
>In a discussion of self-modifying code, I've seen a reference to a toolbox
>call "MakeDataExecutable". I can't find any documentation on this call in IM:
>Memory, Think Ref., or in Apple's Headers. Anyone know where I can get some
>info on it?
It's in the latest Universal Headers. Checking the headers included with
CodeWarrior 7, the routine is declared in OSUtils.p as
{$IFC GENERATINGPOWERPC }
PROCEDURE MakeDataExecutable(baseAddress: UNIV Ptr; length: LONGINT);
{$ENDC}
and in OSUtils.h as
#if GENERATINGPOWERPC
extern pascal void MakeDataExecutable(void *baseAddress, unsigned long length);
#endif
MakeDataExecutable was first documented in issue 18 of develop magazine;
check out the sidebar on caching on page 53 of that issue. Note that the
sidebar suggests FlushInstructionCache as a 68K counterpart to
MakeDataExecutable, but these days where possible it is preferable to call
FlushCodeCacheRange to flush 68K code, as specifying the range can avoid
needless speed hits when running under the DR Emulator.
FlushCodeCacheRange is documented in tech note HW 6 - "Cache as Cache
Can".
Grobbins grobbins@znet.com
---------------------------
>From erichsen@pacificnet.net (Erichsen)
Subject: Q: Open-Close PPP from Code?
Date: Wed, 27 Sep 1995 14:19:14 -0700
Organization: Disorganized
Is there any way to open and close a MacPPP connection programmatically?
I'd like to manually open, soft close, and hard close PPP without having
to go to the control panel.
+++++++++++++++++++++++++++
>From Dave Overton <doverton@iglou.com>
Date: Thu, 28 Sep 1995 14:03:25 GMT
Organization: DataStream Imaging Systems, Inc.
If you look at the code to the MacPPP Control Panel,
it will tell you how to do this.
This code is extracted from the cdev source.
case SOFTCLOSEBTN:
case HARDCLOSEBTN:
if ( Gestalt((OSType) 'PPP ', (long *) &lap) == noErr) {
if (lap && lap->lapClose && lap->transProc) {
(*(lap->lapClose))(lap); /* close PPP */
if ( (item - numitems) == SOFTCLOSEBTN) {
lap->ppp_flags |= CLOSE_PPP;
(*(lap->transProc))(TransitionOpen);
}
updatecp(p, dlogp, numitems);
}
}
break;
case OPENBTN:
if ( Gestalt((OSType) 'PPP ', (long *) &lap) == noErr) {
if (lap) {
if (lap->transProc == nil) {
if (noErr == OpenDriver("\p.IPP",&type)) { /* open TCP */
CntrlParam tiopb;
#define ipctlGetAddr 15 /* csCode to get our IP address */
bzero((b_8 *)&tiopb, sizeof(tiopb));
tiopb.ioCRefNum = type;
tiopb.csCode = ipctlGetAddr;
PBControl((ParamBlockRec *) &tiopb, false);
}
} else
(*(lap->transProc))(TransitionOpen);
updatecp(p, dlogp, numitems);
}
}
break;
Dave Overton
+++++++++++++++++++++++++++
>From rocknrog@intac.com (Roger D. Placer)
Date: Fri, 29 Sep 1995 15:51:54 -0400
Organization: Virtuoso Software Consulting
In article <DFMCDp.EML@iglou.com>, Dave Overton <doverton@iglou.com> wrote:
> This code is extracted from the cdev source.
>
> case SOFTCLOSEBTN:
> case HARDCLOSEBTN:
[re: PPP soft close and hard close]
I always wondered what the hell the difference was, and unless there's
some critical source missing that would contradict what was quoted, it
would appear that they both execute the exact same code. Funky!
+++++++++++++++++++++++++++
>From erichsen@pacificnet.net (Erichsen)
Date: Fri, 29 Sep 1995 13:27:02 -0700
Organization: Disorganized
In article <rocknrog-2909951551540001@blmfld-s5.intac.com>,
rocknrog@intac.com (Roger D. Placer) wrote:
>I always wondered what the hell the difference was, and unless there's
>some critical source missing that would contradict what was quoted, it
>would appear that they both execute the exact same code. Funky!
If you soft close, the next time a program tries to open PPP, it will try
to re-connect. If it was hard closed, it won't.
If you look, it does this on a soft close in addition to all the stuff it
does on a hard close (From the MacPPP source):
if( ( item - numitems ) == SOFTCLOSEBTN )
{
lap->ppp_flags |= CLOSE_PPP;
( *( lap->transProc ) )( TransitionOpen );
}
This appears to be the only difference, programmatically, from a soft or
hard close.
---------------------------
>From andrewwelc@aol.com (AndrewWelc)
Subject: QuickTime JPEG help
Date: 20 Sep 1995 08:48:47 -0400
Organization: America Online, Inc. (1-800-827-6364)
I'm attempting to use QuickTime's Image Compression Manager to display
generic, cross-platform JPEG images. It looks simple enough: just use the
FDecompressImage() routine with a custom proc to spool the JPEG data from
the file.
However this routine expects an ImageDescriptionHandle that tells it
certain things about the image, such as the compressor that was used, the
size of the image, the resolution, etc.
So the question is: is there any kind of a built-in routine that will
extract this information from a generic JPEG file for me, or do I have to
go in and munge around in the JPEG, building the ImageDescriptionHandle
myself?
Any help would be most appreciated.
Regards,
Andrew Welch
Thaumaturgist
Ambrosia Software, Inc.
..........
For the latest versions of our software, technical support, and Ambrosia
news, stop by and visit the Ambrosia Software, Inc. support forums:
America Online ---> Keyword: Ambrosia
CompuServe ---> GO word: Ambrosia
eWorld --> Shortcut: Ambrosia
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro)
Date: Fri, 22 Sep 1995 16:11:14 +1200
Organization: University of Waikato
In article <43p2jf$dgr@newsbf02.news.aol.com>, andrewwelc@aol.com
(AndrewWelc) wrote:
>I'm attempting to use QuickTime's Image Compression Manager to display
>generic, cross-platform JPEG images. It looks simple enough: just use the
>FDecompressImage() routine with a custom proc to spool the JPEG data from
>the file.
>
>However this routine expects an ImageDescriptionHandle that tells it
>certain things about the image, such as the compressor that was used, the
>size of the image, the resolution, etc.
>
>So the question is: is there any kind of a built-in routine that will
>extract this information from a generic JPEG file for me, or do I have to
>go in and munge around in the JPEG, building the ImageDescriptionHandle
>myself?
You have to munge around in the JPEG and build the ImageDescriptionHandle
yourself. Here's a routine to extract the bounds of the image:
PROCEDURE FindPictureSize
(
JpegData : ADDRESS;
JpegDataSize : LONGCARD;
VAR PictureSize : Point
);
(* scans the JPEG data, looking for the information about
the dimensions of the image. *)
VAR
NextByte, DataEnd : ADDRESS;
TwoBytes :
RECORD
CASE : CARDINAL OF
| 1:
HighByte, LowByte : BYTE;
| 2:
SignedWord : ShortInt
END (*CASE*)
END (*RECORD*);
BEGIN
NextByte := JpegData;
DataEnd := JpegData + JpegDataSize;
LOOP
IF NextByte = DataEnd THEN
ErrorLiteral('couldn’t determine JPEG image bounds',
ProcessingError);
EXIT
END (*IF*);
IF ORD(NextByte^) = 0FFH THEN
INC(NextByte);
IF NextByte = DataEnd THEN
ErrorLiteral('malformed JPEG file', ProcessingError);
EXIT
END (*IF*);
IF ORD(NextByte^) = 0C0H THEN
INC(NextByte);
IF DataEnd - NextByte >= 7 THEN
NextByte := NextByte + 3;
TwoBytes.HighByte := NextByte^;
INC(NextByte);
TwoBytes.LowByte := NextByte^;
INC(NextByte);
PictureSize.v := TwoBytes.SignedWord;
TwoBytes.HighByte := NextByte^;
INC(NextByte);
TwoBytes.LowByte := NextByte^;
INC(NextByte);
PictureSize.h := TwoBytes.SignedWord;
EXIT
ELSE
ErrorLiteral('malformed bounds info', ProcessingError);
EXIT
END (*IF*)
END (*IF*)
ELSE
INC(NextByte)
END (*IF*)
END (*LOOP*)
END FindPictureSize;
+++++++++++++++++++++++++++
>From quinn@quinn.echidna.id.au (Quinn "The Eskimo!")
Date: Fri, 22 Sep 1995 12:08:55 +0800
Organization: Underemployed, and loving it!
In article <43p2jf$dgr@newsbf02.news.aol.com>, andrewwelc@aol.com
(AndrewWelc) wrote:
>So the question is: is there any kind of a built-in routine that will
>extract this information from a generic JPEG file for me, or do I have to
>go in and munge around in the JPEG, building the ImageDescriptionHandle
>myself?
Aaron Giles' JPEG library (on the Apprentice CD and most probably
elsewhere) demonstrates this.
Share and Enjoy.
--
Quinn "The Eskimo!" <http://www.quinn.echidna.id.au/Quinn/WWW/>
"Not now Blaznee, I'm busy sealing the doom of countless millions."
Note the new email address. Check my web page for the full story.
+++++++++++++++++++++++++++
>From tgl@netcom.com (Tom Lane)
Date: Sat, 23 Sep 1995 15:57:29 GMT
Organization: Netcom Online Communications Services
ldo@waikato.ac.nz (Lawrence D'Oliveiro) writes:
> You have to munge around in the JPEG and build the ImageDescriptionHandle
> yourself. Here's a routine to extract the bounds of the image:
> [ code omitted ]
The code Lawrence posted is dangerously oversimplified. It will fail if
the JPEG file uses a non-baseline SOF marker. (SOF1, FFC1, is reasonably
common; SOF2, FFC2, will soon be common with the spread of progressive
JPEGs.) Worse, it can be fooled by an FFC0 sequence that happens to occur
within the body of some other marker. For example, if fed a JPEG image
that contains a JPEG-compressed thumbnail per the JFIF 1.02 spec, this
code will return the dimensions of the thumbnail rather than of the main
image.
You can find code to do it right in any number of places. A heavily
commented C version is in the file rdjpgcom.c in the IJG code
(ftp.uu.net:/graphics/jpeg/jpegsrc.v6.tar.gz). Aaron Giles posted
Mac-specific code many moons ago. I dunno if Aaron's code is still
available on the net, but I think it's on the Apprentice CD for Mac
developers. Apple themselves probably provide suitable code somewhere
in their QuickTime developer info.
regards, tom lane
organizer, Independent JPEG Group
+++++++++++++++++++++++++++
>From 100336.230@compuserve.com (Faustino Forcén)
Date: 24 Sep 1995 03:28:34 GMT
Organization: VEGA & Asociados
In article <43p2jf$dgr@newsbf02.news.aol.com>, andrewwelc@aol.com
(AndrewWelc) wrote:
> So the question is: is there any kind of a built-in routine that will
> extract this information from a generic JPEG file for me, or do I have to
> go in and munge around in the JPEG, building the ImageDescriptionHandle
> myself?
Andrew
I didn´t wrote the original code. I took it from AppleLink and adapted it
to my own set of image reading/writing classes.
BTW, the JPEG images created with QuickTime are PICT files, but the data
(once passed the 512 bytes header) is a JFIF file.
hope it helps
Faustino Forcén
Bugmeister
Vega & Asociados
#define JFIF_ID_MARKER 0xE0
#define JFIF_INFO_MARKER 0xC0
// miFile : Original file
// dim : destination size for the image
// miOffscreen : where to put the image
// invierte : if I want to invert the palette.
OSErr TJPEG::GetImagen(FSSpec miFile, Rect *dim, GWorldPtr *miOffScreen,
Boolean invierte)
{
Rect srcRect, destRect;
GDHandle gdh;
CGrafPtr port;
Byte *data = nil, *s, id[5] = "JFIF";
long length, i;
short j, refnum, err, width, height;
Point imagenSize;
PixMapHandle pix;
ImageDescriptionHandle descH;
short modo;
if (*miOffScreen)
DisposeGWorld(*miOffScreen);
*miOffScreen = nil;
err = FSpOpenDF(&miFile, fsRdPerm, &refnum);
if (!err)
{
err = GetEOF(refnum, &length);
if (!err && length < 170L)
err = -1;
if (!err)
{
data = (Byte*)NewPtr(length);
if (!data)
err = memFullErr;
}
if (!err)
err = FSRead(refnum, &length, data);
FSClose(refnum);
}
if (!err)
{
// make sure data is JFIF data stream
for (i = 0; i < length; ++i)
{
if (data[i] == 0xFF && data[i+1] == JFIF_ID_MARKER)
{
for (s = &data[i+4], j = 0; j < 5; ++s, ++j)
{
if (*s != id[j])
{
err = -1;
j = 5;
}
}
i = length;
}
}
if (err)
goto abortJPEG;
// read JPEG height and width from JFIF stream
err = -1;
for (i = 0; i < length; ++i)
{
if (data[i] == 0xFF && data[i+1] == JFIF_INFO_MARKER)
{
height = data[i+5]*256 + data[i+6];
width = data[i+7]*256 + data[i+8];
err = noErr;
i = length;
}
}
if (!err)
{
srcRect.top = 0;
srcRect.left = 0;
srcRect.bottom = height;
srcRect.right = width;
imagenSize.h = srcRect.right;
imagenSize.v = srcRect.bottom;
// hay que calcular el tamaño optimo para escalar
calculaRect(&destRect, &imagenSize, dim, escalaBoth);
err = NewGWorld(miOffScreen, 24, &destRect, nil, nil, 0);
GetGWorld(&port, &gdh);
SetGWorld(*miOffScreen, nil);
ClipRect(&destRect);
ForeColor(blackColor);
BackColor(whiteColor);
// a brand new imgdeschdl based on the jfif data
descH = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
HLock((Handle)descH);
(*descH)->idSize = sizeof(ImageDescription);
(*descH)->cType = 'jpeg';
(*descH)->resvd1 = 0L;
(*descH)->resvd2 = 0;
(*descH)->dataRefIndex = 0;
(*descH)->version = 1;
(*descH)->revisionLevel = 1;
(*descH)->vendor = 'appl';
(*descH)->temporalQuality = 0;
(*descH)->spatialQuality = 0;
(*descH)->width = width;
(*descH)->height = height;
(*descH)->vRes = (*descH)->hRes = Long2Fix(72L);
(*descH)->dataSize = length;
(*descH)->frameCount = 1;
BlockMove("\pPhoto - JPEG", (*descH)->name, 32L);
(*descH)->depth = 24;
(*descH)->clutID = -1;
HUnlock((Handle)descH);
pix = GetGWorldPixMap(*miOffScreen);
// invierte is for some agency images that have an inverted palette
if(invierte)
modo = ditherCopy + notSrcCopy;
else
modo = ditherCopy;
if (LockPixels(pix))
{
err = DecompressImage((Ptr)data, descH, pix,
&srcRect, &destRect, modo, nil);
UnlockPixels(pix);
}
else
err = memFullErr;
SetGWorld(port, gdh); // restore port and device
DisposeHandle((Handle)descH);
}
}
abortJPEG:
if (data)
DisposePtr((Ptr)data);
return err;
}
// eof
--
Blenders of good code since 1988
---------------------------
>From winterp@spot.Colorado.EDU (WINTER PAUL RUDOLPH)
Subject: Storing data in text portion of an application
Date: 27 Sep 95 17:37:31 GMT
Organization: University of Colorado at Boulder
I have a protocal question:
Is it proper to store data in the data portion of an application? There is
too much of it to comfortably store it as resources, so that option is not
available. At the start of the program, the application would open is data
fork, read in the data, and then close it again. Is this proper, and if so,
how dangerous is it to the integrity of the application?
Thanks for any advice/thoughts on this. If it can't/shouldn't be done I can
always stick with the external file that must be kept with the program.
Paul Winter
+++++++++++++++++++++++++++
>From pandhphot@aol.com (PandH Phot)
Date: 27 Sep 1995 17:07:06 -0400
Organization: America Online, Inc. (1-800-827-6364)
This is an opinion, not a fact. I have done what you say, and it works
just fine. But as a USER of software I REALLY HATE apps that do this. They
always seem to end up destroying themselves during a poorly-timed crash.
Frankly, modifying the app's resource fork during operation has the same
limitation, and I could live without that, too.
I much prefer the use of some sort of external file (preferences or some
such).
But as I say, it's an opinion.
paul
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <erkyrath+@CMU.EDU>
Date: Wed, 27 Sep 1995 17:05:39 -0400
Organization: Carnegie Mellon, Pittsburgh, PA
winterp@spot.Colorado.EDU (WINTER PAUL RUDOLPH) writes:
> Is it proper to store data in the data portion of an application? There is
> too much of it to comfortably store it as resources, so that option is not
> available. At the start of the program, the application would open is data
> fork, read in the data, and then close it again. Is this proper, and if so,
> how dangerous is it to the integrity of the application?
There's nothing specifically wrong with it. However, it's a great pain
to do in a PPC native or fat application. The PPC code is stored in
the data fork, and you'd have to diddle the code fragment resource to
make sure the PPC code and your data don't overlap. I don't know if
there are any development systems which arrange this for you
automatically.
You'd be amazed how much data can be stored in the resource fork,
though. I've got a 6-meg resource file in the project I'm working on
now. The only disadvantage is that it's hard to read in just part of
a resource -- but since you say you're reading all the data at the
start of the program, that shouldn't concern you.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <erkyrath+@CMU.EDU>
Date: Wed, 27 Sep 1995 18:53:23 -0400
Organization: Carnegie Mellon, Pittsburgh, PA
pandhphot@aol.com (PandH Phot) writes:
> This is an opinion, not a fact. I have done what you say, and it works
> just fine. But as a USER of software I REALLY HATE apps that do this. They
> always seem to end up destroying themselves during a poorly-timed crash.
> Frankly, modifying the app's resource fork during operation has the same
> limitation, and I could live without that, too.
I assume you're talking about *modifying* the application's data fork
as it runs. I agree that that is absolutely to be avoided at all
costs. But I think the original poster just meant storing some
read-only data in the data fork.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From triple@nando.net (Joe Zobkiw)
Date: Wed, 27 Sep 1995 20:30:01 -0400
Organization: TripleSoft Inc.
In article <winterp.812223451@spot.Colorado.EDU>,
winterp@spot.Colorado.EDU (WINTER PAUL RUDOLPH) wrote:
>Is it proper to store data in the data portion of an application? There is
>too much of it to comfortably store it as resources, so that option is not
>available. At the start of the program, the application would open is data
>fork, read in the data, and then close it again. Is this proper, and if so,
>how dangerous is it to the integrity of the application?
This is perfectly legitimate EXCEPT that by default PowerPC code is stored
in the data fork of native applications. Mind you, you can change the way
this works (store your PowerPC code in a resource, for example) but then
you lose some of the advantages of data fork resident code such as Virtual
Memory paging, etc.
I would suggest creating a separate file called "Application Data" or
somesuch, place it in the same folder as the application, and read from it
instead.
Joe Zobkiw
President
- ----------------------------------------------------------------
TripleSoft Inc, Macintosh Software Development CIS: 74631,1700
P.O. Box 30774, Raleigh, NC 27622-0774 AOL/eWorld: TripleSoft
voice/fax (919) 872-0916 Internet: Triple@nando.net
- ----------------------------------------------------------------
Look for "A Fragment of Your Imagination" from Addison-Wesley...
PowerPC/Code Resources/Fragments/Components/Extensions/and more...
+++++++++++++++++++++++++++
>From winterp@spot.Colorado.EDU (WINTER PAUL RUDOLPH)
Date: 28 Sep 95 14:57:50 GMT
Organization: University of Colorado at Boulder
>>Is it proper to store data in the data portion of an application? There is
>>too much of it to comfortably store it as resources, so that option is not
>>available. At the start of the program, the application would open is data
>>fork, read in the data, and then close it again. Is this proper, and if so,
>>how dangerous is it to the integrity of the application?
>This is perfectly legitimate EXCEPT that by default PowerPC code is stored
>in the data fork of native applications. Mind you, you can change the way
>this works (store your PowerPC code in a resource, for example) but then
>you lose some of the advantages of data fork resident code such as Virtual
>Memory paging, etc.
The application I am working on will not becreated specificaly for a Power
PC, as I don't have access to a compiler which creates aps for PowerPC.
This being the case, do I still have to worry about code in the data fork?
>From all the responses I've gotten, I'm inclined to stick with the external
file, but I'm just curious now.
Thanks to everyone who responded!!!
Paul Winter
---------------------------
>From eddyg@vcd.hp.com (Eddy J. Gurney)
Subject: Why doesn't the Dialog Manager recognize I moved some controls?
Date: 11 Sep 1995 17:55:32 GMT
Organization: Hewlett-Packard
I have a dialog box with several buttons in it. In some cases, I would
like to swap the location of two buttons. I easily accomplish this with
a couple of calls to MoveControl() after I've called GetNewDialog() and
before I show it. The controls *look* like they've swapped locations,
but when the user clicks on them (or points to them with Balloon Help
active), the Dialog Manager tells me they clicked on the "original"
button.
Example:
The dialog buttons are stored (and sometimes used) like this:
( Cancel ) ( OK )
So I call MoveControl to put the OK button where the Cancel button is
and the Cancel button where the OK button is:
( OK ) ( Cancel )
But now when the user clicks on "OK", the Dialog Manager tells me they
clicked on Cancel and vice versa. I don't understand this; aftera all,
the OK button is still item 1 and the Cancel button still item 2, just
in new locations.
Any ideas?
Thanks,
Eddy
P.S. Please don't tell me this is bad UI and that I shouldn't be doing
this. I already know that. I just want to know that answer to this
problem. ;-)
+++++++++++++++++++++++++++
>From dstone@chem.utoronto.ca (David Stone)
Date: Mon, 11 Sep 1995 18:27:08 GMT
Organization: University of Toronto Chemistry
In article <431t6k$97e@news.vcd.hp.com>, eddyg@vcd.hp.com (Eddy J. Gurney)
wrote:
>
> I have a dialog box with several buttons in it. In some cases, I would
> like to swap the location of two buttons. I easily accomplish this with
> a couple of calls to MoveControl() after I've called GetNewDialog() and
> before I show it. The controls *look* like they've swapped locations,
> but when the user clicks on them (or points to them with Balloon Help
> active), the Dialog Manager tells me they clicked on the "original"
> button.
====snip=====
The dialog manager keeps its own list of DITL items that includes their
rects. This list is unaffected by MoveControl and so the dialog manager
continues to believe that the items are where they were originally.
>
> P.S. Please don't tell me this is bad UI and that I shouldn't be doing
> this. I already know that. I just want to know that answer to this
> problem. ;-)
OK, I won't! My guess would be you'd have to use AppendDITL and
ShortenDITL
to move them, ie. physically take the items out of the DITL, and add them
back in with the new position. An easier thing to do might be to implement
a "state" variable which flags which positions you are using for the
buttons, then simply swap the control titles. Of course, you'll have to
switch the itemHit value depending on the "state" flag, which is still
ugly. And you'll also have to deal with complaints about items moving
from your users, but there you go.
Dave Stone
+++++++++++++++++++++++++++
>From resorcerer@aol.com (Resorcerer)
Date: 12 Sep 1995 00:58:49 -0400
Organization: America Online, Inc. (1-800-827-6364)
Eddy -
>The controls *look* like they've swapped locations,
>but when the user clicks on them (or points to them with Balloon Help
>active), the Dialog Manager tells me they clicked on the "original"
>button.
You have to move the controls (ControlHandles) as well as the Control
items in the dialog's item list. The Control items are what the Dialog
Manager and Help Manager pay attention to, but the ControllHandles are
what the window updating pays attention to.
Doug McKenna
Mathemaesthetics, Inc.
PS. Try this routine to see if it works...
void PlaceDialogControlItem(DialogPtr dlog, short item, Rect *bounds)
{
short type; ControlHandle hndl; Rect box;
GetDItem(dlog,item,&type,(Handle *)&hndl,&box);
type &= ~itemDisable;
if (type==(ctrlItem+btnCtrl) || type==(ctrlItem+radCtrl) ||
type==(ctrlItem+chkCtrl) || type==(ctrlItem+resCtrl))
(*hndl)->contrlRect = *bounds;
SetDItem(dlog,item,type,(Handle)hndl,bounds);
}
+++++++++++++++++++++++++++
>From Richard Wesley <hawkfish@punchdeck.com>
Date: 12 Sep 1995 14:50:55 GMT
Organization: Punch Deck Consulting
dstone@chem.utoronto.ca (David Stone) wrote:
>In article <431t6k$97e@news.vcd.hp.com>, eddyg@vcd.hp.com (Eddy J. Gurney)
>wrote:
>>
>> I have a dialog box with several buttons in it. In some cases, I would
>> like to swap the location of two buttons. I easily accomplish this with
>> a couple of calls to MoveControl() after I've called GetNewDialog() and
>> before I show it. The controls *look* like they've swapped locations,
>> but when the user clicks on them (or points to them with Balloon Help
>> active), the Dialog Manager tells me they clicked on the "original"
>> button.
>====snip=====
>
>The dialog manager keeps its own list of DITL items that includes their
>rects. This list is unaffected by MoveControl and so the dialog manager
>continues to believe that the items are where they were originally.
Exactly.
>
>>
>> P.S. Please don't tell me this is bad UI and that I shouldn't be doing
>> this. I already know that. I just want to know that answer to this
>> problem. ;-)
>
>OK, I won't! My guess would be you'd have to use AppendDITL and
>ShortenDITL
>to move them, ie. physically take the items out of the DITL, and add them
>back in with the new position. An easier thing to do might be to implement
This is like using tactical nuclear weapons to kill a fly. Just do a
::GetDialogItem
::SetDialogItem
and change the Rect argument between the calls. You might find it useful
to call ::HideDialogItem and ::ShowDialogItem while you move things around.
Don't forget about ::S/GetDefaultItem and ::S/GetCancelItem and moving your
hilite item.
>a "state" variable which flags which positions you are using for the
>buttons, then simply swap the control titles. Of course, you'll have to
>switch the itemHit value depending on the "state" flag, which is still
>ugly. And you'll also have to deal with complaints about items moving
>from your users, but there you go.
This is likely to be confusing for everybody and won't fix the Balloon
Help problem.
- rmgw
Who hasn't looked at the Dialog Manager in years until he had to write yet
another lightweight UI framework based on it last week...
http://www.punchdeck.com/hawkfish/PunchDeck.html
- --------------------------------------------------------------------------
Richard Wesley hawkfish@punchdeck.com | "'Hand it round first, and cut it
Punch Deck Consulting pnchdeck@aol.com | afterwards.'" - Lewis Carroll,
Macintosh Software Development | "Through the Looking Glass"
- --------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From dstone@chem.utoronto.ca (David Stone)
Date: Tue, 12 Sep 1995 18:12:30 GMT
Organization: University of Toronto Chemistry
In article <4346of$666@news.halcyon.com>, Richard Wesley
<hawkfish@punchdeck.com> wrote:
>
> dstone@chem.utoronto.ca (David Stone) wrote:
> >In article <431t6k$97e@news.vcd.hp.com>, eddyg@vcd.hp.com (Eddy J. Gurney)
> >wrote:
===snip====
> >OK, I won't! My guess would be you'd have to use AppendDITL and
> >ShortenDITL
> >to move them, ie. physically take the items out of the DITL, and add them
> >back in with the new position. An easier thing to do might be to implement
>
> This is like using tactical nuclear weapons to kill a fly. Just do a
>
> ::GetDialogItem
> ::SetDialogItem
>
Duh! Of course, I could always claim that I was deliberately making it
hard to discourage "improper" user interface activities. Now where have
I seen that tactic before.....
Dave Stone
+++++++++++++++++++++++++++
>From David Shortt <wyatt@wyatt.com>
Date: 13 Sep 1995 06:05:01 GMT
Organization: Wyatt Technology Corp.
>In article <431t6k$97e@news.vcd.hp.com>, eddyg@vcd.hp.com (Eddy J. Gurney)
>wrote:
>>
>> I have a dialog box with several buttons in it. In some cases, I would
>> like to swap the location of two buttons. I easily accomplish this with
>> a couple of calls to MoveControl() after I've called GetNewDialog() and
>> before I show it. The controls *look* like they've swapped locations,
>> but when the user clicks on them (or points to them with Balloon Help
>> active), the Dialog Manager tells me they clicked on the "original"
>> button.
I use the following routine:
procedure MoveMyItemRel (theDialog: dialogPtr;
itemNum: integer;
dh, dv: integer);
{moves a dialog control item by (dh,dv)}
var
theType: integer;
theHandle: handle;
theBox: rect;
begin
GetDialogItem(theDialog, itemNum, theType, theHandle, theBox);
if BAND(theType, ctrlItem) = ctrlItem then
MoveControl(ControlHandle(theHandle), theBox.left + dh, theBox.top + dv);
with theBox do begin
left := left + dh;
right := right + dh;
top := top + dv;
bottom := bottom + dv;
end;
SetDialogItem(theDialog, itemNum, theType, theHandle, theBox);
end;
I found that I had to move the control _and_ call SetDialogItem. Hope this helps.
Dave Shortt
wyatt@wyatt.com
+++++++++++++++++++++++++++
>From mouser@zercom.net (Martin-Gilles Lavoie)
Date: Wed, 27 Sep 1995 20:54:33 -0500
Organization: nil
In article <435sad$bs3@ocean.silcom.com>, David Shortt <wyatt@wyatt.com> wrote:
> >In article <431t6k$97e@news.vcd.hp.com>, eddyg@vcd.hp.com (Eddy J. Gurney)
> >wrote:
> >>
> >> I have a dialog box with several buttons in it. In some cases, I would
> >> like to swap the location of two buttons. I easily accomplish this with
> >> a couple of calls to MoveControl() after I've called GetNewDialog() and
> >> before I show it. The controls *look* like they've swapped locations,
> >> but when the user clicks on them (or points to them with Balloon Help
> >> active), the Dialog Manager tells me they clicked on the "original"
> >> button.
>
> I use the following routine:
>
> procedure MoveMyItemRel (theDialog: dialogPtr;
> itemNum: integer;
> dh, dv: integer);
> {moves a dialog control item by (dh,dv)}
> var
> theType: integer;
> theHandle: handle;
> theBox: rect;
> begin
> GetDialogItem(theDialog, itemNum, theType, theHandle, theBox);
> if BAND(theType, ctrlItem) = ctrlItem then
> MoveControl(ControlHandle(theHandle), theBox.left + dh, theBox.top + dv);
> with theBox do begin
> left := left + dh;
> right := right + dh;
> top := top + dv;
> bottom := bottom + dv;
> end;
> SetDialogItem(theDialog, itemNum, theType, theHandle, theBox);
> end;
>
> I found that I had to move the control _and_ call SetDialogItem. Hope
this helps.
>
An answer to this behaviour is that the Dialog Manager looks through it's
Dialog Item List handle ('ditl') for the first item wich returns true on
PtInRect() (also giving the dialog manager it's anoying back-to-front
order).
Once it finds a targeted rect, it uses it's itemHandle to reference a
control. I.e., it doesn't find the control using FindControl().
MGL
Martin-Gilles Lavoie
- ------------------------------------------------------------------------------
MPW: Because life is too complicated for CodeWarrior.
- ------------------------------------------------------------------------------
---------------------------
>From dstone@chem.utoronto.ca (David Stone)
Subject: [Q] Changing Pixmap resolution???
Date: Fri, 22 Sep 1995 16:53:44 GMT
Organization: University of Toronto Chemistry
Looking at the Pixmap data structure, there are two fields for
resolution (hRes, vRes, both Fixed). Is it possible to set these
to values other than 72 dpi?? Specifically, could I create a Pixmap
offscreen with the same resolution as a LaserWriter (300 dpi)?
The reason for asking is problems printing large symbols (up to 0.25")
in graphs created using quickdraw calls. If the graph is bigger than
the page (it usually is), it has to be scaled to fit (typically 87%
reduction). When this is done, circles frequently become ellipses
and squares rectangles on the printed version because of mismatch
of the pixel locations between the screen and printer page.
I want to try drawing the graph into a Pixmap at the same resolution
as the printer and then Copybits or Open/Close/DrawPicture to the
printer page.
Does Copybits cope with different resolution images? How?
I'm already drawing the screen graph offscreen and CopyBitsing it
into the approriate location - could I Copybits the offscreen
image (@ 72 dpi) into the printer port (@ 300 dpi)???
Please email response as well as post.
David Stone
dstone@chem.utoronto.ca
Thanks!
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro)
Date: Tue, 26 Sep 1995 15:55:48 +1200
Organization: University of Waikato
In article <dstone-220995125502@csgmac.chem.utoronto.ca>,
dstone@chem.utoronto.ca (David Stone) wrote:
>Looking at the Pixmap data structure, there are two fields for
>resolution (hRes, vRes, both Fixed). Is it possible to set these
>to values other than 72 dpi?? Specifically, could I create a Pixmap
>offscreen with the same resolution as a LaserWriter (300 dpi)?
...
>Does Copybits cope with different resolution images? How?
>I'm already drawing the screen graph offscreen and CopyBitsing it
>into the approriate location - could I Copybits the offscreen
>image (@ 72 dpi) into the printer port (@ 300 dpi)???
I don't think the resolution fields in the PixMap mean much with current
versions of QuickDraw. But yes, you _can_ create QuickDraw pictures
containing pixels at any resolution you desire. The trick lies in the
relative dimensions of the srcRect and dstRect arguments to CopyBits: for
example, if the source rectangle is (0, 0, 300, 300) and the destination
one is (0, 0, 72, 72), then your source bitmap/pixmap is interpreted as
having an effective resolution of 300 pixels per inch.
I was doing this trick with the LaserWriter driver several years ago, and
it worked a treat. I could generate the 300-dpi bitmaps in my code, paste
them into Microsoft Word, and print them from there at full quality.
Of course, if your application is handling the printing directly, you can
go one better: use PrGeneral to enquire the available printer resolutions,
set the printer port to a suitably high resolution, and then all your
drawing into that port will take place at that resolution.
---------------------------
>From st955901@pilot.stu.cowan.edu.au (Philip Cummins)
Subject: [Q] Traps not callable from interrupt, why?
Date: Sun, 24 Sep 1995 17:59:38 +0800
Organization: Edith Cowan University
Hello,
Is there any way I can call an a-trap listed as 'do not call from
interrupt' from an interrupt safely? And what exactly is the reason why we
can't call them?
Thanks,
Philip
--
Please exert your creativity to convince yourself there's a signature here.
+++++++++++++++++++++++++++
>From reinder@neuretp.biol.ruu.nl (Reinder Verlinde)
Date: Sun, 24 Sep 1995 15:04:15 +0200
Organization: Rijksuniversiteit Utrecht
In article <st955901-2409951759380001@ppp29.cowan.edu.au>,
st955901@pilot.stu.cowan.edu.au (Philip Cummins) wrote:
) Hello,
)
) Is there any way I can call an a-trap listed as 'do not call from
) interrupt' from an interrupt safely? And what exactly is the reason why we
) can't call them?
)
You can't call most of them because they may move memory, and the memory
manager is not reentrant. I guess you could try and hack your way around it
by creating a heap zone to be used solely by your interrupt routine, and
doing a SetZone (If SetZone is not interrupt safe this trick does not work)
to that zone in your interrupt handler. If you do that you should not
only save the current zone (via a GetZone/SetZone pair), but also the
current internal state of the memory manager, and that is undocumented.
You should also ensure not to do anything in the System heap, so calls
like SetFont, DrawString, maybe even LineTo and PenSize etc. are a nono.
I don't know whether there will be many routines which can be fixed this
way.
Reinder Verlinde
>From the index of Inside Macintosh:
"Human interface Guidelines: see User interface Guidelines"
I wonder what they are aiming at. Monkeys? Aliens? Mice?
+++++++++++++++++++++++++++
>From triple@nando.net (Joe Zobkiw)
Date: Sun, 24 Sep 1995 09:46:04 -0400
Organization: TripleSoft Inc.
In article <st955901-2409951759380001@ppp29.cowan.edu.au>,
st955901@pilot.stu.cowan.edu.au (Philip Cummins) wrote:
>Is there any way I can call an a-trap listed as 'do not call from
>interrupt' from an interrupt safely? And what exactly is the reason why we
>can't call them?
Probably not. The reason you can't call most patches from an interrupt
that are labeled as such is because they move memory or depend on the
state of the OS being a certain way that is not guaranteed to be that way
during interrupt time.
If it says you can't do it, you can't do it. Mind you, some may not be
labeled as such but may also be problematic to call from an interrupt as
well. For example, if someone patched a trap that is OK to call from
interrupt time but moves memory in their patch. This could cause problems.
Hope this helps.
Joe Zobkiw
- ----------------------------------------------------------------
TripleSoft Inc, Macintosh Software Development CIS: 74631,1700
P.O. Box 30774, Raleigh, NC 27622-0774 AOL/eWorld: TripleSoft
voice/fax (919) 872-0916 Internet: Triple@nando.net
- ----------------------------------------------------------------
Look for "A Fragment of Your Imagination" from Addison-Wesley...
PowerPC/Code Resources/Fragments/Components/Extensions/and more...
+++++++++++++++++++++++++++
>From Binky the Wonderwhorse <binky@mmcorp.com>
Date: 25 Sep 1995 10:37:23 GMT
Organization: MultiMedia Corporation
lo,
Some calls you can...the Async calls can be done so you can do PBControl
calls, PBFileBlurb calls and stuff so long as they're done asynchronously.
Seem to be a bit of a black art...and a bit stupid to have these
ridiculous restrictions imposed but I shan't start bitching...honest
Binky
+++++++++++++++++++++++++++
>From Richard Wesley <hawkfish@punchdeck.com>
Date: 25 Sep 1995 14:26:18 GMT
Organization: Punch Deck Consulting
Binky the Wonderwhorse <binky@mmcorp.com> wrote:
>lo,
>
>Some calls you can...the Async calls can be done so you can do PBControl
>calls, PBFileBlurb calls and stuff so long as they're done asynchronously.
>
>Seem to be a bit of a black art...and a bit stupid to have these
>ridiculous restrictions imposed but I shan't start bitching...honest
Its not really a black art - you are in a seperate thread and can only make
calls that are reentrant. Shared resources must be managed by locks and
semaphores in such situations.
Large parts of the toolbox do not have such management facilities. Most
significantly, the Memory Manager maintains a pool of memory for the main
thread and cannot be used by the interrupt level thread. This means that
amything that uses the memory manager cannot be called. Most other
resources you allocate from the system (e.g. GUI elements etc.) have similar
restrictions. The notable exceptions are resources that can be accessed by
adding something to a queue and waiting for the result. This means all
drivers that allow asynchronous parameter blocks requests and some other
managers that also allow such requests (e.g. SndDoCommand). And anything
that manipulates only data from your interrupt level thread
(e.g. BlockMoveData).
- rmgw
http://www.punchdeck.com/hawkfish/PunchDeck.html
- --------------------------------------------------------------------------
Richard Wesley hawkfish@punchdeck.com | "What was that popping sound?"
Punch Deck Consulting pnchdeck@aol.com | "A paradigm shifting without a
Macintosh Software Development | clutch." - Dilbert (Scott Adams)
- --------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From reed@medicine.wustl.edu (Thomas Reed)
Date: Tue, 26 Sep 1995 09:20:55 -0500
Organization: Washington University
In article <st955901-2409951759380001@ppp29.cowan.edu.au>,
st955901@pilot.stu.cowan.edu.au (Philip Cummins) wrote:
>Is there any way I can call an a-trap listed as 'do not call from
>interrupt' from an interrupt safely? And what exactly is the reason why we
>can't call them?
It looks like others have adequately answered why you can't call them, but
no one has mentioned a solution. The best solution in such a case is to
just set a global flag to let you know that you need to do something.
Then, somewhere, from some code that gets called frequently (and, more
importantly, that doesn't execute at interrupt time), check that flag and
do the appropriate thing.
Note that I've never done this before, I just know the principles. So,
don't ask me for practical help, as I have none to give (except to say
that the book "Power Macintosh Programming Starter Kit" has an example of
exactly this case).
-Thomas
=====================================================
Thomas Reed Washington University
reed@visar.wustl.edu Medical School
reed@medicine.wustl.edu Saint Louis, MO
http://medinfo.wustl.edu/~reed
- ---------------------------------------------------
Clothes make the man. Naked people have little or no
influence on society. -- Mark Twain
=====================================================
Opinions posted are not the opinions of Wash. U.
+++++++++++++++++++++++++++
>From isis@netcom.com (Mike Cohen)
Date: Tue, 26 Sep 1995 18:11:09 GMT
Organization: ISIS International
st955901@pilot.stu.cowan.edu.au (Philip Cummins) writes:
>Hello,
>Is there any way I can call an a-trap listed as 'do not call from
>interrupt' from an interrupt safely? And what exactly is the reason why we
>can't call them?
No. The reason you can't call them is becuse those traps can move memory.
Remember that interrupts can occur asynchronously at unpredictable times
and the memory manager may be in some inconsistant state in the middle of
moving some block of memory. Since the memory manager is non-reentrant, if
you tried to do something that could move memory when it's already in the
process of moving memory, "unpredictable" results could happen.
--
Mike Cohen - isis@netcom.com
Home Page: ftp://ftp.netcom.com/pub/is/isis/home.html
Sound is the same for all the world - Youssou N'dour, "Eyes Open"
---------------------------
End of C.S.M.P. Digest
**********************